<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        //当问到这种问题的时候，我觉得应该先讲一下vue2.x使用的Object.defineProperty，然后再解释他有什么不好，再解释vue3中使用的proxy
        //Vue的响应式原理
        //Object.defineProperty源码实现
        //Proxy源码实现
        //Vue3.0Composition API设计动机

        /*
        关于响应式系统，vue2.x和vue3.0的版本在实现响应式的原理上还是有很大的不同的
        vue2.x中将 data选项对象中的所有属性，通过使用 Object.defineProperty 把这些属性全部转为 getter/setter，
        再get和set方法中进行拦截，利用发布订阅的设计模式，在get方法中进行订阅，在set方法中发布通知，让所有订阅者完成响应。

        vue3.0中使用proxy对象重写响应式，将一个普通对象设置为响应式对象，通过proxy代理
        proxy可以拦截属性的访问get，赋值set，删除deleteProperty，再结合依赖收集
        然后在get中收集依赖，把当前的key与effect对应起来，触发收集依赖函数track，
        在set中当新老值不相等的时候，触发trigger，重新让栈数组中的effect执行
        */

        /*
        区别
        1.默认会递归；数组的push，pop等不触发视图更新；对象不存在的属性不能被拦截；如果对象的层级比较大，就会无限递归，导致内存溢出
        2.vue3,可以监听数组变化；可以直接新增属性，新增的属性也会被代理；可以劫持整个对象；
        操作时不是对原对象操作,是 new Proxy 返回的一个新代理对象
        */

        //1.Object.defineProperty无法监控到数组下标的变化，导致通过数组下标添加元素，不能实时响应。对象不存在的属性不能被拦截
        //2.Object.defineProperty只能劫持对象的属性，从而需要对每个对象，每个属性进行遍历，如果属性值是对象还要深度递归遍历
        //3.Proxy可以劫持整个对象，并返回一个新的代理对象
        //4.Proxy不仅可以代理对象，还可以代理数组，还可以代理动态添加的属性。
    </script>
</body>
</html>